package com.sinosoft.weixin.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sinosoft.weixin.config.FuncFlagConfig;
import com.sinosoft.weixin.config.InterfaceAdapterConfig;
import com.sinosoft.weixin.controller.dto.RequestDTO;
import com.sinosoft.weixin.controller.dto.RequestHeadDTO;
import com.sinosoft.weixin.controller.dto.request.CheckWorkNumDTO;
import com.sinosoft.weixin.controller.dto.response.LoginStatusDTO;
import com.sinosoft.weixin.controller.dto.response.LoginStatusResponseDTO;
import com.sinosoft.weixin.controller.vo.LoginInfoVo;
import com.sinosoft.weixin.controller.vo.LoginVo;
import com.sinosoft.weixin.controller.vo.Vo;
import com.sinosoft.weixin.db.entity.LoginLog;
import com.sinosoft.weixin.db.entity.LoginLogExample;
import com.sinosoft.weixin.db.entity.User;
import com.sinosoft.weixin.db.entity.UserExample;
import com.sinosoft.weixin.db.mapper.LoginLogMapper;
import com.sinosoft.weixin.db.mapper.UserMapper;
import com.sinosoft.weixin.service.MessageService;
import com.sinosoft.weixin.shiro.ShiroUtils;
import com.sinosoft.weixin.utils.HttpClientUtils;
import com.sinosoft.weixin.utils.MyDateUtils;
import com.sinosoft.weixin.utils.RandomUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * Created by huzhengying on 2017/11/12.
 * 登陆控制器
 */
@RestController
@RequestMapping("api")
public class HomeController {
    private static org.apache.logging.log4j.Logger logger = LogManager.getLogger(HomeController.class);
    private ObjectMapper objectMapper = new ObjectMapper();
    private static final String SUCCESS_STATUS = "0";
    private static final String FAIL_STATUS = "1";

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LoginLogMapper loginLogMapper;
    @Autowired
    private MessageService messageService;
    @Autowired
    private InterfaceAdapterConfig interfaceAdapterConfig;

    /**
     *  1、校验工号是否有效
     *  2、判断是否已经登陆过
     *  3、未登陆，先校验工号、手机号、姓名是否有效
     *  4、校验验证码
     */
    @RequestMapping(value = "home")
    public Object home(@RequestParam("weChatId")String weChatId){
        try{
            UserExample userExample = new UserExample();
            userExample.createCriteria().andWeChatIdEqualTo(weChatId);
            List<User> users = userMapper.selectByExample(userExample);
            //如果该微信有过登陆记录，先判断对应工号是否有效
            if(null != users && users.size() > 0){
                User user = users.get(0);
                RequestHeadDTO requestHeadDTO =
                        new RequestHeadDTO(UUID.randomUUID().toString(), FuncFlagConfig.LOGIN_FUNC_FLAG);
                CheckWorkNumDTO checkWorkNumDTO = new CheckWorkNumDTO();
                checkWorkNumDTO.setAgentCode(user.getWorkNumber());
                RequestDTO requestDTO = new RequestDTO(requestHeadDTO,checkWorkNumDTO);

                //判断工号是否有效
                String checkWorkNumberResult = HttpClientUtils.sendHttpRequest(
                        objectMapper.writeValueAsString(requestDTO),
                        interfaceAdapterConfig.getContextUrl(InterfaceAdapterConfig.LOGIN));
                LoginStatusResponseDTO responseDTO = objectMapper.readValue(checkWorkNumberResult,LoginStatusResponseDTO.class);
                logger.info(objectMapper.writeValueAsString(responseDTO));

                //0为工号校验成功
                LoginStatusDTO loginStatusDTO = responseDTO.getHead();
                if(SUCCESS_STATUS.equals(loginStatusDTO.getFlag())){
                    insertLoginLog(user.getWorkNumber(),SUCCESS_STATUS,loginStatusDTO.getDesc());
                    Subject subject = SecurityUtils.getSubject();
                    SecurityUtils.getSubject().getSession().setTimeout(-1);
                    UsernamePasswordToken token = new UsernamePasswordToken(user.getWeChatId(),user.getWorkNumber());
                    subject.login(token);
                    return LoginVo.loginSucc(user.getWorkNumber());
                //1为工号校验失败,校验失败解绑该微信号对应的工号
                }else {
                    userExample = new UserExample();
                    userExample.createCriteria().andWeChatIdEqualTo(weChatId);
                    users = userMapper.selectByExample(userExample);
                    if(users != null && users.size() > 0){
                        userMapper.deleteByExample(userExample);
                    }

                    userExample = new UserExample();
                    userExample.createCriteria().andWorkNumberEqualTo(user.getWorkNumber());
                    users = userMapper.selectByExample(userExample);
                    if(users != null && users.size() > 0){
                        userMapper.deleteByExample(userExample);
                    }
                    insertLoginLog(user.getWorkNumber(),FAIL_STATUS,loginStatusDTO.getDesc());
                    return LoginVo.loginFail(LoginVo.Login);
                }
            }else {
                //未登陆跳转到登陆页面
                return LoginVo.loginFail(LoginVo.Login);
            }
        }catch (Exception ex){
            logger.error("系统异常！",ex);
        }
        return LoginVo.loginFail(LoginVo.Login);
    }

    @RequestMapping(value = "getLoginInfo")
    public Object getLoginInfo(){
        try{
            return ShiroUtils.getCurrentUserPrincipal();
        }catch (Exception ex){
            return Vo.fail("获取登陆信息失败!");
        }
    }

    @RequestMapping(value = "checkLoginInfo",method = RequestMethod.POST)
    public Object checkLoginInfo(LoginInfoVo loginInfoVo,HttpServletRequest httpServletRequest){
        try{
            logger.info(String.format("验证三项基本信息:%s",objectMapper.writeValueAsString(loginInfoVo)));
            String workNumber = loginInfoVo.getWorkNumber();
            LoginLogExample loginLogExample = new LoginLogExample();
            loginLogExample.createCriteria().
                    andWorkNumberEqualTo(workNumber).
                    andStatusEqualTo(FAIL_STATUS).
                    andLoginDateLessThan(MyDateUtils.getCurrentMaxTime()).
                    andLoginDateGreaterThan(MyDateUtils.getCurrentMinTime());
            List<LoginLog> loginLogs = loginLogMapper.selectByExample(loginLogExample);
            if(loginLogs.size() >= 3){
                return Vo.fail("登陆失败次数超过三次，请核对后于明天重试！");
            }

            //发送校验信息
            RequestHeadDTO requestHeadDTO =
                    new RequestHeadDTO(UUID.randomUUID().toString(), FuncFlagConfig.LOGIN_FUNC_FLAG);
            CheckWorkNumDTO checkWorkNumDTO = new CheckWorkNumDTO();
            checkWorkNumDTO.setMobile(loginInfoVo.getMobile());
            checkWorkNumDTO.setAgentCode(loginInfoVo.getWorkNumber());
            checkWorkNumDTO.setName(loginInfoVo.getName());
            RequestDTO requestDTO = new RequestDTO(requestHeadDTO,checkWorkNumDTO);
            String loginResult = HttpClientUtils.sendHttpRequest(
                    objectMapper.writeValueAsString(requestDTO),
                    interfaceAdapterConfig.getContextUrl(InterfaceAdapterConfig.LOGIN));
            LoginStatusResponseDTO loginStatusResponseDTO = objectMapper.readValue(loginResult,LoginStatusResponseDTO.class);
            logger.info(String.format("验证三项信息返回结果:%s",objectMapper.writeValueAsString(loginStatusResponseDTO)));

            LoginStatusDTO loginStatusDTO = loginStatusResponseDTO.getHead();
            if(SUCCESS_STATUS.equals(loginStatusDTO.getFlag())){
                //验证成功生成验证码
                String verificationCode = RandomUtil.getRandomNum(4);
                logger.info(String.format("姓名:%s,工号:%s,验证码:%s",
                        loginInfoVo.getName(),
                        loginInfoVo.getWorkNumber(),
                        verificationCode));
                HttpSession session = httpServletRequest.getSession();
                session.setAttribute(workNumber,verificationCode);
                session.setAttribute(verificationCode,new Date());
                //发送短信
                Map<String,String> params = new HashMap<>();
                params.put("verificationCode",verificationCode);
                messageService.sendMessage(loginInfoVo.getWorkNumber(),"GCS0001",loginInfoVo.getMobile(),params);

                return Vo.succ("身份信息校验成功!");
            }else {
                insertLoginLog(workNumber,FAIL_STATUS,"身份信息校验失败!");
                return Vo.fail(loginStatusDTO.getDesc());
            }
        }catch (Exception ex){
            logger.error(ex);
            return Vo.fail("系统异常！");
        }
    }

    @RequestMapping(value = "login",method = RequestMethod.POST)
    public Object login(LoginInfoVo loginInfoVo,HttpServletRequest httpServletRequest){
        try {
            logger.info(String.format("验证码登陆接口:%s",objectMapper.writeValueAsString(loginInfoVo)));
            HttpSession session = httpServletRequest.getSession();
            String verificationCode = (String)session.getAttribute(loginInfoVo.getWorkNumber());
            Date createDate = (Date)session.getAttribute(verificationCode);
            //验证码校验
            if(((new Date()).getTime() - createDate.getTime()) < 60000){
                if(StringUtils.isNotBlank(loginInfoVo.getVerificationCode())
                        && loginInfoVo.getVerificationCode().equals(verificationCode)){
                    //如果该工号已经绑定过微信号，则将之前的绑定信息删除，保证工号与微信号只能绑定一次
                    UserExample userExample = new UserExample();
                    userExample.createCriteria().andWorkNumberEqualTo(loginInfoVo.getWorkNumber());
                    List<User> users = userMapper.selectByExample(userExample);
                    if(users != null && users.size() > 0){
                        userMapper.deleteByExample(userExample);
                    }
                    userExample = new UserExample();
                    userExample.createCriteria().andWeChatIdEqualTo(loginInfoVo.getWeChatId());
                    users = userMapper.selectByExample(userExample);
                    if(users != null && users.size() > 0){
                        userMapper.deleteByExample(userExample);
                    }

                    //验证码校验成功，将微信号与工号绑定
                    User user = new User();
                    user.setWorkNumber(loginInfoVo.getWorkNumber());
                    user.setWeChatId(loginInfoVo.getWeChatId());
                    user.setMakeDate(new Date());
                    user.setMobile(loginInfoVo.getMobile());
                    user.setName(loginInfoVo.getName());
                    user.setStatus(SUCCESS_STATUS);
                    userMapper.insert(user);
                    //记录登陆信息
                    Subject subject = SecurityUtils.getSubject();
                    SecurityUtils.getSubject().getSession().setTimeout(-1);
                    UsernamePasswordToken token = new UsernamePasswordToken(loginInfoVo.getWeChatId(),loginInfoVo.getWorkNumber());
                    subject.login(token);
                    return Vo.succ("登陆成功!");
                }else {
                    return Vo.fail("验证码不匹配!");
                }
            }else {
                return Vo.fail("验证码失效!");
            }
        }catch (Exception ex){
            logger.error(ex);
        }
        return Vo.fail("登陆失败!");
    }

    private void insertLoginLog(String workNumber,String status,String remark){
        LoginLog loginLog = new LoginLog();
        loginLog.setWorkNumber(workNumber);
        loginLog.setLoginDate(new Date());
        loginLog.setStatus(status);
        loginLog.setRemark(remark);
        loginLogMapper.insert(loginLog);
    }

}
